<?php

namespace app\api\controller;
//use EasyWeChat\Factory;
use think\facade\Db;

class Payment
{

    protected $appid = null;
    protected $mchnt_cd = null;
    protected $mchnt_key = null;
    protected $daylog = null;
    protected $time = null;
    protected $redis = null;
    public function __construct()
    {
        $this -> appid = \config('pay.miniprogram.app_id');
        $this -> mchnt_cd = \config('pay.miniprogram.mch_id');
        $this -> mchnt_key = \config('pay.miniprogram.key');
        $this-> daylog = \config('pay.miniprogram.log');
        $this -> time = date('Y年m月d日 H时m分s秒 ');
        $this -> redis = new \fast\Redis();
//        $this->config['notify_url'] = request()->domain().'/api/payment/notify';//支付完成回调地址url,不能带参数
    }


    public function paybalance($ordersn,$totalPrice,$uaerbalance,$type=""){
        Db::startTrans();
        if($type == 'yuyue'){
            $resinfo = Db::name('reservation_item') -> where('r_ordersn',$ordersn) -> find();
            $endtime =$resinfo['appointment'] ." ". explode('-',$resinfo['restime'])[1];
            $endtime =  strtotime($endtime) - time() ;
            $key  = 'yu_zf_exp:' . $ordersn;//拼接订单类型及订单号 未支付
            if($endtime > 0 ){
                $this -> redis->setex($key, $endtime, $ordersn); // 设置订单过期时间为5秒
            }
            $res1 = Db::name('reservation_item')
                -> where('r_ordersn',$ordersn)
                -> update(['status'=>2,'paytime'=>time(),'payordersn'=>payordersn($uaerbalance['id']),'paymentmethod' => 'balance']);

        }else if($type == 'ordergood'){
            $res1 = Db::name('orders')
                -> where('order_sn',$ordersn)
                -> update([
                    'status'=>2,
                    'paytime'=>time(),
                    'payordersn'=>payordersn($uaerbalance['id']),
                    'payment_method' => 'balance'
                ]);
        }
        if(!$res1){
            Db::rollback();
            return 2;
        }
        $after = floatval($uaerbalance['balance']) - floatval($totalPrice);
        Db::name('user') -> where('id',$uaerbalance['id']) -> update(['balance'=>$after]);
        //查询余额
        $data = [
            'user_id' => $uaerbalance['id'],
            'before' => $uaerbalance['balance'],
            'after' => $after,
            'money' => $totalPrice,
            'state' => 2,
            'type' => 'balance',
            'ordersn' =>  $ordersn,
            'memo' => '余额支付'.$totalPrice."元",
            'createtime' => time(),
        ];

        $res = Db::name('user_money_log') -> insert($data);
        if(!$res){
            Db::rollback();
            return 2;
        }
        Db::commit();
        return 1;
    }

    public function Xcx_order($out_trade_no,$fee,$openid,$ordertype=""){
        //支付相关设置
        $total_fee = $fee * 100;// 微信支付单位是分，所以这里需要*100
        $trade_type = 'JSAPI';//交易类型 默认JSAPI   LPXS
        if($ordertype == ''){
            $notify_url = request()->domain().'/api/payment/notify_url'; //支付完成回调地址url,不能带参数
        }else{
            $notify_url = request()->domain().'/api/payment/notify_goodurl'; //支付完成回调地址url,不能带参数
        }

        //这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错
        $post['mchnt_cd'] =  $this -> mchnt_cd;
        $post['order_amt'] = floatval($total_fee);//总金额
        $post['mchnt_order_no'] = $out_trade_no;//商户订单号
        $post['notify_url'] = $notify_url;//通知URL
        $post['sign'] = $this -> sign($post);
        $post['reserved_trade_type'] = $trade_type;
        $post['sub_openid'] = $openid; //用户的openid
        $post['sub_appid'] = $this -> appid ; //appid
//        $url = 'https://aipaytest.fuioupay.com/aggregatePay/xcxPreCreate';//测试地址
         $url = "https://aipay.fuioupay.com/aggregatePay/xcxPreCreate";
//        $url = "https://aipay-xs.fuioupay.com/aggregatePay/xcxPreCreate";
        $result = $this -> post_request($url,json_encode($post));
        $result = json_decode($result,true);

//        write_log('paylog',$this -> time.'返回数据:uid='.$uid.' data='.json_encode($result)."sign_str=".$result,'web_get_paydata');
        if($result['result_code'] == '000000' || $result['result_code'] == 'SUCCESS' ) {
            $data['result_code'] = 1;
            $data['timeStamp'] = $result['sdk_timestamp']; //时间戳
            $data['random_str'] = $result['sdk_noncestr']; //签名算法，暂支持 MD5
            $data['signType'] = $result['sdk_signtype']; //签名算法，暂支持 MD5
            $data['package'] = $result['sdk_package']; //统一下单接口返回的 prepay_id 参数值，提交格式如：prepay_id=*
            $data['paySign'] = $result['sdk_paysign']; //签名,具体签名方案参见微信公众号支付帮助文档;
            $data['out_trade_no'] = $out_trade_no;
        }else{
            $data['result_code'] = 0;
            $data['result_msg'] = $result['result_msg'];
            $data['mchnt_cd'] = $result['mchnt_cd'];
        }
        return $data;
    }


    public function post_request($url,$data){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json',
                'Content-Length: ' . strlen($data))
        );
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }

    /* * 服务器通知notify_url
         */
    public function notify_url(){
        $post = file_get_contents('php://input');
        $post_data = json_decode($post,true);
        //  验签配置
        $tmp = [
            'result_code' => $post_data['result_code'],
            'result_msg' => $post_data['result_msg'],
            'mchnt_cd' => $post_data['mchnt_cd'],
            'reserved_fy_trace_no' => $post_data['reserved_fy_trace_no'],
            'random_str ' => $post_data['random_str'],
        ];
        $sign = $this -> sign($tmp);
        if(isset($post_data['mchnt_order_no']) && isset($post_data['sign']) && $sign){
            Db::startTrans();
            $orderinfo = Db::name('reservation_item')-> where('r_ordersn', $post_data['mchnt_order_no'])->find();
            if (empty($orderinfo)) { // 如果订单不存在 或者 订单已经支付过了
                Db::rollback();
                write_log('paylog','订单库中无此记录');
            }else{
                $endtime =$orderinfo['appointment'] ." ". explode('-',$orderinfo['restime'])[1];
                $endtime =  strtotime($endtime) - time();
                $key  = 'yu_zf_exp:' . $post_data['mchnt_order_no'];//拼接订单类型及订单号 未支付
                if($endtime > 0 ){
                    $this -> redis->setex($key, $endtime, $post_data['mchnt_order_no']); // 设置订单过期时间为5秒
                }
               $resinfo = Db::name('reservation_item')
                    ->where('r_ordersn', $post_data['mchnt_order_no'])
                    ->update(['status' => 2, 'paytime' => time(),'payordersn'=>payordersn($orderinfo['uid']),'paymentmethod'=> 'wechat']);
                if(!$resinfo){
                    Db::rollback();
                    write_log('paylog','调用失败');
                }
                //查询余额
                $data = [
                    'user_id' => $orderinfo['uid'],
                    'money' => $orderinfo['pay_amount'],
                    'state' => 2,
                    'type' => 'wechat',
                    'ordersn' =>  $post_data['mchnt_order_no'],
                    'memo' => '微信支付'.$orderinfo['pay_amount']."元",
                    'createtime' => time(),
                ];
                $res = Db::name('user_money_log') -> insert($data);
                if(!$res){
                    Db::rollback();
                    return 0;
                }
                Db::commit();
                write_log('paylog',$this -> time .' 单号：'.$post_data['mchnt_order_no'].',金额：'. $post_data['order_amt'] .'  支付成功');
            }
           return 1;
        }else{
            //验签失败
            write_log('paylog','验签失败:'.$post.' sign签名:'.$sign);
            return 0;
        }
    }
    public function notify_goodurl(){
        $post = file_get_contents('php://input');
        $post_data = json_decode($post,true);
        //  验签配置
        $tmp = [
            'result_code' => $post_data['result_code'],
            'result_msg' => $post_data['result_msg'],
            'mchnt_cd' => $post_data['mchnt_cd'],
            'reserved_fy_trace_no' => $post_data['reserved_fy_trace_no'],
            'random_str ' => $post_data['random_str'],
        ];
        $sign = $this -> sign($tmp);
        if(isset($post_data['mchnt_order_no']) && isset($post_data['sign']) && $sign){
            Db::startTrans();
            $orderid = Db::name('orders')-> where('order_sn', $post_data['mchnt_order_no'])->find();
            if(!$orderid){
                Db::rollback();
                write_log('paylog','订单库中无此记录');
            }else{
                Db::name('orders')
                    ->where('id', $orderid['id'])
                    ->update(['status' => 2, 'pay_status' => 1, 'paytime' => time(),'payordersn'=>payordersn($orderid['user_id']),'payment_method'=>'wechat']);
                //查询余额
                $data = [
                    'user_id' => $orderid['user_id'],
                    'money' => $orderid['payment_price'],
                    'state' => 2,
                    'type' => 'wechat',
                    'ordersn' =>  $post_data['mchnt_order_no'],
                    'memo' => '微信支付'.$orderid['payment_price']."元",
                    'createtime' => time(),
                ];
                $res = Db::name('user_money_log') -> insert($data);
                if(!$res){
                    Db::rollback();
                    return 0;
                }
                Db::commit();
                write_log('paylog',$this -> time .' 单号：'.$post_data['mchnt_order_no'].',金额：'. $post_data['order_amt'] .'  支付成功');
            }
            return 1;
        }else{
            //验签失败
            write_log('paylog','验签失败:'.$post.' sign签名:'.$sign);
            return 0;
        }
    }
    //签名 $data要先排好顺序
    private function sign($data){
        $stringA = '';
        foreach ($data as $key=>$value){
            if(!$value) continue;
            if($stringA) $stringA .= '|'.$value;
            else $stringA = $value;
        }
        $stringSignTemp = $stringA.'|'.$this -> mchnt_key;
        return strtoupper(md5($stringSignTemp));
    }


}